<!--
访问统计快速预览组件
显示最近7天的访问趋势和关键统计数据
-->
<script setup lang="ts">
import type { EchartsUIType } from '@vben/plugins/echarts';

import type {
  AccessStats,
  AccessTrendChart,
  BrowserStats,
  DeviceStats,
  PopularPage,
  RegionStats,
} from '#/api/monitor/access';

import { onActivated, onMounted, onUnmounted, ref } from 'vue';

import { AnalysisChartCard } from '@vben/common-ui';
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';

import {
  getAccessStats,
  getAccessTrend,
  getBrowserStats,
  getDeviceStats,
  getPopularPages,
  getRegionStats,
} from '#/api/monitor/access';

// 组件状态
const accessStats = ref<AccessStats | null>(null);
const trendData = ref<AccessTrendChart | null>(null);
const regionStats = ref<RegionStats[]>([]);
const deviceStats = ref<DeviceStats[]>([]);
const popularPages = ref<PopularPage[]>([]);
const browserStats = ref<BrowserStats[]>([]);
const loading = ref(false);
const error = ref<null | string>(null);

// Echarts相关
const chartRef = ref<EchartsUIType>();
const { renderEcharts, resize } = useEcharts(chartRef);

// 定时器
let refreshTimer: NodeJS.Timeout | null = null;

/**
 * 获取访问统计数据
 */
async function fetchAccessData() {
  try {
    loading.value = true;
    error.value = null;

    const [stats, trend, regions, devices, pages, browsers] = await Promise.all(
      [
        getAccessStats(),
        getAccessTrend(),
        getRegionStats(),
        getDeviceStats(),
        getPopularPages(),
        getBrowserStats(),
      ],
    );

    accessStats.value = stats;
    trendData.value = trend;
    regionStats.value = regions;
    deviceStats.value = devices;
    popularPages.value = pages;
    browserStats.value = browsers;

    // 更新图表
    updateChart(trend);
  } catch (error_) {
    console.error('获取访问统计失败:', error_);
    error.value = '获取访问统计失败';
  } finally {
    loading.value = false;
  }
}

/**
 * 更新Echarts图表
 */
function updateChart(trend: AccessTrendChart) {
  if (!chartRef.value) return;

  const option = {
    tooltip: {
      trigger: 'axis',
      backgroundColor: 'rgba(255, 255, 255, 0.95)',
      borderColor: '#e0e0e0',
      borderWidth: 1,
      textStyle: {
        color: '#333',
        fontSize: 12,
      },
      formatter(params: any[]) {
        let html = `<div style="font-weight: bold; margin-bottom: 5px;">${params[0].axisValue}</div>`;
        params.forEach((param, index) => {
          const color = param.color;
          const name = param.seriesName;
          const value = param.value;
          html += `<div style="margin: 2px 0;">
            <span style="display: inline-block; width: 10px; height: 10px; background-color: ${color}; border-radius: 50%; margin-right: 8px;"></span>
            ${name}: <span style="font-weight: bold;">${value}</span>
          </div>`;
        });
        return html;
      },
    },
    legend: {
      data: ['访问量', '独立访客', '页面浏览量'],
      bottom: 10,
      textStyle: {
        fontSize: 12,
      },
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '15%',
      top: '10%',
      containLabel: true,
    },
    xAxis: {
      type: 'category',
      data: trend.dates,
      axisLine: {
        lineStyle: {
          color: '#e0e0e0',
        },
      },
      axisLabel: {
        textStyle: {
          fontSize: 11,
          color: '#666',
        },
      },
    },
    yAxis: {
      type: 'value',
      axisLine: {
        show: false,
      },
      axisTick: {
        show: false,
      },
      axisLabel: {
        textStyle: {
          fontSize: 11,
          color: '#666',
        },
      },
      splitLine: {
        lineStyle: {
          color: '#f0f0f0',
          type: 'dashed',
        },
      },
    },
    series: [
      {
        name: '访问量',
        type: 'bar',
        data: trend.visits,
        itemStyle: {
          color: '#5470c6',
          borderRadius: [2, 2, 0, 0],
        },
        barMaxWidth: 30,
        emphasis: {
          itemStyle: {
            color: '#4c63d2',
          },
        },
      },
      {
        name: '独立访客',
        type: 'line',
        data: trend.uniqueVisitors,
        smooth: true,
        lineStyle: {
          color: '#91cc75',
          width: 2,
        },
        itemStyle: {
          color: '#91cc75',
        },
        symbol: 'circle',
        symbolSize: 4,
      },
      {
        name: '页面浏览量',
        type: 'line',
        data: trend.pageViews,
        smooth: true,
        lineStyle: {
          color: '#fac858',
          width: 2,
        },
        itemStyle: {
          color: '#fac858',
        },
        symbol: 'circle',
        symbolSize: 4,
      },
    ],
  };

  renderEcharts(option);
}

/**
 * 格式化数字显示
 */
function formatNumber(num: number): string {
  if (num >= 10_000) {
    return `${(num / 10_000).toFixed(1)}w`;
  } else if (num >= 1000) {
    return `${(num / 1000).toFixed(1)}k`;
  }
  return num.toString();
}

/**
 * 计算增长率
 */
function calculateGrowth(current: number, previous: number): number {
  if (previous === 0) return 0;
  return Math.round(((current - previous) / previous) * 100);
}

/**
 * 设置定时刷新
 */
function setupRefresh() {
  // 每2分钟刷新一次数据
  refreshTimer = setInterval(
    () => {
      fetchAccessData();
    },
    2 * 60 * 1000,
  );
}

/**
 * 清理定时器
 */
function clearRefresh() {
  if (refreshTimer) {
    clearInterval(refreshTimer);
    refreshTimer = null;
  }
}

// 生命周期钩子
onMounted(() => {
  fetchAccessData();
  setupRefresh();
});

onActivated(() => {
  // 从其他页面切换回来时调用resize
  resize();
});

onUnmounted(() => {
  clearRefresh();
});
</script>

<template>
  <AnalysisChartCard title="访问统计">
    <div class="relative h-80">
      <!-- 加载状态 -->
      <div
        v-if="loading"
        class="flex h-full items-center justify-center text-gray-500"
      >
        <div class="flex items-center space-x-2">
          <div
            class="h-4 w-4 animate-spin rounded-full border-2 border-blue-500 border-t-transparent"
          ></div>
          <span>正在获取访问数据...</span>
        </div>
      </div>

      <!-- 错误状态 -->
      <div
        v-else-if="error"
        class="flex h-full items-center justify-center text-red-500"
      >
        <div class="text-center">
          <div class="mb-2">📊</div>
          <div>{{ error }}</div>
          <button
            class="mt-2 rounded bg-red-100 px-3 py-1 text-sm transition-colors hover:bg-red-200"
            @click="fetchAccessData"
          >
            重试
          </button>
        </div>
      </div>

      <!-- 图表和统计数据 -->
      <div v-else class="flex h-full flex-col">
        <!-- 关键指标摘要 -->
        <div v-if="accessStats" class="mb-4 grid grid-cols-4 gap-3">
          <div
            class="rounded-lg border border-blue-200 bg-blue-50 p-2 text-center"
          >
            <div class="text-lg font-semibold text-blue-600">
              {{ formatNumber(accessStats.todayVisits) }}
            </div>
            <div class="text-xs text-gray-500">今日访问</div>
            <div
              class="text-xs"
              :class="
                calculateGrowth(
                  accessStats.todayVisits,
                  accessStats.yesterdayVisits,
                ) >= 0
                  ? 'text-green-500'
                  : 'text-red-500'
              "
            >
              {{
                calculateGrowth(
                  accessStats.todayVisits,
                  accessStats.yesterdayVisits,
                ) >= 0
                  ? '↑'
                  : '↓'
              }}
              {{
                Math.abs(
                  calculateGrowth(
                    accessStats.todayVisits,
                    accessStats.yesterdayVisits,
                  ),
                )
              }}%
            </div>
          </div>

          <div
            class="rounded-lg border border-green-200 bg-green-50 p-2 text-center"
          >
            <div class="text-lg font-semibold text-green-600">
              {{ formatNumber(accessStats.weekVisits) }}
            </div>
            <div class="text-xs text-gray-500">本周访问</div>
            <div
              class="text-xs"
              :class="
                calculateGrowth(
                  accessStats.weekVisits,
                  accessStats.lastWeekVisits,
                ) >= 0
                  ? 'text-green-500'
                  : 'text-red-500'
              "
            >
              {{
                calculateGrowth(
                  accessStats.weekVisits,
                  accessStats.lastWeekVisits,
                ) >= 0
                  ? '↑'
                  : '↓'
              }}
              {{
                Math.abs(
                  calculateGrowth(
                    accessStats.weekVisits,
                    accessStats.lastWeekVisits,
                  ),
                )
              }}%
            </div>
          </div>

          <div
            class="rounded-lg border border-purple-200 bg-purple-50 p-2 text-center"
          >
            <div class="text-lg font-semibold text-purple-600">
              {{ formatNumber(accessStats.activeUsers) }}
            </div>
            <div class="text-xs text-gray-500">活跃用户</div>
          </div>

          <div
            class="rounded-lg border border-orange-200 bg-orange-50 p-2 text-center"
          >
            <div class="text-lg font-semibold text-orange-600">
              {{ formatNumber(accessStats.pageViews) }}
            </div>
            <div class="text-xs text-gray-500">页面浏览</div>
          </div>
        </div>

        <!-- 图表区域 -->
        <div class="mb-4 h-40">
          <EchartsUI ref="chartRef" height="100%" width="100%" />
        </div>

        <!-- 详细数据区域 -->
        <div class="grid grid-cols-3 gap-3 text-xs">
          <!-- 地域分布 -->
          <div class="rounded-lg border bg-gray-50 p-3">
            <div class="mb-2 font-medium text-gray-700">地域分布</div>
            <div class="space-y-1">
              <div
                v-for="region in regionStats.slice(0, 4)"
                :key="region.region"
                class="flex justify-between"
              >
                <span class="text-gray-600">{{ region.region }}</span>
                <span class="text-gray-800">{{ region.percentage }}%</span>
              </div>
            </div>
          </div>

          <!-- 设备类型 -->
          <div class="rounded-lg border bg-gray-50 p-3">
            <div class="mb-2 font-medium text-gray-700">设备类型</div>
            <div class="space-y-1">
              <div
                v-for="device in deviceStats"
                :key="device.deviceType"
                class="flex justify-between"
              >
                <span class="text-gray-600">{{ device.deviceType }}</span>
                <span class="text-gray-800">{{ device.percentage }}%</span>
              </div>
            </div>
          </div>

          <!-- 热门页面 -->
          <div class="rounded-lg border bg-gray-50 p-3">
            <div class="mb-2 font-medium text-gray-700">热门页面</div>
            <div class="space-y-1">
              <div
                v-for="page in popularPages.slice(0, 4)"
                :key="page.path"
                class="flex justify-between"
              >
                <span class="truncate text-gray-600">{{ page.title }}</span>
                <span class="text-gray-800">{{
                  formatNumber(page.visits)
                }}</span>
              </div>
            </div>
          </div>
        </div>

        <!-- 浏览器统计 -->
        <div
          v-if="browserStats.length > 0"
          class="mt-3 rounded-lg border bg-gray-50 p-3"
        >
          <div class="mb-2 text-xs font-medium text-gray-700">浏览器分布</div>
          <div class="flex justify-between text-xs">
            <div
              v-for="browser in browserStats.slice(0, 5)"
              :key="browser.browser"
              class="text-center"
            >
              <div class="text-gray-600">{{ browser.browser }}</div>
              <div class="font-medium text-gray-800">
                {{ browser.percentage }}%
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </AnalysisChartCard>
</template>

<style scoped>
/* 自定义样式 */
.animate-spin {
  animation: spin 1s linear infinite;
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>
